/**
 * 中文DOM封装 (zh-dom.js)
 * 支持DOM操作、元素查找与创建、类操作、事件处理、链式调用
 * 中文方法命名 + JSDoc 参数提示
 */

class DOM操作 {
  /**
   * 构造函数 - 创建DOM操作实例
   * @param {HTMLElement|string} 目标 元素或选择器
   */
  constructor(目标) {
    this._元素 = 目标 instanceof HTMLElement 
      ? 目标 
      : typeof 目标 === 'string' 
        ? document.querySelector(目标) 
        : null;
  }

  /**
   * 获取原始DOM元素
   * @returns {HTMLElement|null} DOM元素或null
   */
  取值() {
    return this._元素;
  }

  /**
   * 查找子元素
   * @param {string} 选择器 CSS选择器
   * @returns {DOM操作|null} 找到的元素实例或null
   */
  查找(选择器) {
    const 子元素 = this._元素.querySelector(选择器);
    return 子元素 ? new DOM操作(子元素) : null;
  }

  /**
   * 查找所有子元素
   * @param {string} 选择器 CSS选择器
   * @returns {DOM操作[]} 找到的元素实例数组
   */
  查找所有(选择器) {
    const 元素列表 = this._元素.querySelectorAll(选择器);
    return Array.from(元素列表).map(元素 => new DOM操作(元素));
  }

  /** 创建元素 */
  static 创建元素(标签名, 属性 = {}, 内容 = '') {
    const 元素 = document.createElement(标签名);
    
    // 设置属性
    for (const [键, 值] of Object.entries(属性)) {
      if (键 === 'class') {
        元素.className = 值;
      } else if (键 === 'style' && typeof 值 === 'object') {
        Object.assign(元素.style, 值);
      } else if (键 === '事件') {
        for (const [事件名, 回调] of Object.entries(值)) {
          元素.addEventListener(事件名, 回调);
        }
      } else {
        元素.setAttribute(键, 值);
      }
    }
    
    // 设置内容
    if (typeof 内容 === 'string') {
      元素.textContent = 内容;
    } else if (内容 instanceof HTMLElement || 内容 instanceof DOM操作) {
      元素.appendChild(内容 instanceof DOM操作 ? 内容.取值() : 内容);
    } else if (Array.isArray(内容)) {
      内容.forEach(子内容 => {
        if (typeof 子内容 === 'string') {
          元素.appendChild(document.createTextNode(子内容));
        } else if (子内容 instanceof HTMLElement || 子内容 instanceof DOM操作) {
          元素.appendChild(子内容 instanceof DOM操作 ? 子内容.取值() : 子内容);
        }
      });
    }
    
    return new DOM操作(元素);
  }

  /** 添加类 */
  添加类(...类名列表) {
    this._元素.classList.add(...类名列表);
    return this;
  }

  /** 删除类 */
  删除类(...类名列表) {
    this._元素.classList.remove(...类名列表);
    return this;
  }

  /** 切换类 */
  切换类(类名, 状态) {
    if (状态 !== undefined) {
      this._元素.classList.toggle(类名, 状态);
    } else {
      this._元素.classList.toggle(类名);
    }
    return this;
  }

  /** 是否包含类 */
  包含类(类名) {
    return this._元素.classList.contains(类名);
  }

  /** 设置文本内容 */
  设置文本(文本) {
    this._元素.textContent = 文本;
    return this;
  }

  /** 获取文本内容 */
  获取文本() {
    return this._元素.textContent;
  }

  /** 设置HTML内容 */
  设置HTML(HTML) {
    this._元素.innerHTML = HTML;
    return this;
  }

  /** 获取HTML内容 */
  获取HTML() {
    return this._元素.innerHTML;
  }

  /** 设置属性 */
  设置属性(键, 值) {
    this._元素.setAttribute(键, 值);
    return this;
  }

  /** 获取属性 */
  获取属性(键) {
    return this._元素.getAttribute(键);
  }

  /** 删除属性 */
  删除属性(键) {
    this._元素.removeAttribute(键);
    return this;
  }

  /** 是否有属性 */
  有属性(键) {
    return this._元素.hasAttribute(键);
  }

  /** 设置多个属性 */
  设置多个属性(属性对象) {
    for (const [键, 值] of Object.entries(属性对象)) {
      this._元素.setAttribute(键, 值);
    }
    return this;
  }

  /** 设置样式 */
  设置样式(键, 值) {
    this._元素.style[键] = 值;
    return this;
  }

  /** 设置多个样式 */
  设置多个样式(样式对象) {
    Object.assign(this._元素.style, 样式对象);
    return this;
  }

  /** 获取样式 */
  获取样式(键) {
    return getComputedStyle(this._元素)[键];
  }

  /** 添加事件监听 */
  事件监听(事件名, 回调, 选项 = false) {
    this._元素.addEventListener(事件名, 回调, 选项);
    return this;
  }

  /** 移除事件监听 */
  移除事件监听(事件名, 回调, 选项 = false) {
    this._元素.removeEventListener(事件名, 回调, 选项);
    return this;
  }

  /** 触发事件 */
  触发事件(事件名, 事件数据 = {}) {
    const 事件 = new CustomEvent(事件名, { 
      detail: 事件数据,
      bubbles: true,
      cancelable: true
    });
    this._元素.dispatchEvent(事件);
    return this;
  }

  /** 添加子元素 */
  添加子元素(子元素) {
    const 元素 = 子元素 instanceof DOM操作 ? 子元素.取值() : 子元素;
    this._元素.appendChild(元素);
    return this;
  }

  /** 在指定位置添加子元素 */
  在前面添加子元素(参考元素, 子元素) {
    const 参考 = 参考元素 instanceof DOM操作 ? 参考元素.取值() : 参考元素;
    const 元素 = 子元素 instanceof DOM操作 ? 子元素.取值() : 子元素;
    this._元素.insertBefore(元素, 参考);
    return this;
  }

  /** 移除子元素 */
  移除子元素(子元素) {
    const 元素 = 子元素 instanceof DOM操作 ? 子元素.取值() : 子元素;
    this._元素.removeChild(元素);
    return this;
  }

  /** 移除自己 */
  移除() {
    if (this._元素.parentNode) {
      this._元素.parentNode.removeChild(this._元素);
    }
    return this;
  }

  /** 克隆元素 */
  克隆(深克隆 = true) {
    const 克隆元素 = this._元素.cloneNode(深克隆);
    return new DOM操作(克隆元素);
  }

  /** 获取父元素 */
  获取父元素() {
    return this._元素.parentNode ? new DOM操作(this._元素.parentNode) : null;
  }

  /** 获取子元素列表 */
  获取子元素() {
    return Array.from(this._元素.children).map(元素 => new DOM操作(元素));
  }

  /** 获取兄弟元素 */
  获取兄弟元素() {
    return Array.from(this._元素.parentNode.children)
      .filter(元素 => 元素 !== this._元素)
      .map(元素 => new DOM操作(元素));
  }

  /** 获取前一个兄弟元素 */
  获取前一个兄弟元素() {
    return this._元素.previousElementSibling ? new DOM操作(this._元素.previousElementSibling) : null;
  }

  /** 获取后一个兄弟元素 */
  获取后一个兄弟元素() {
    return this._元素.nextElementSibling ? new DOM操作(this._元素.nextElementSibling) : null;
  }

  /** 获取元素位置和大小 */
  获取位置() {
    return this._元素.getBoundingClientRect();
  }

  /** 检查元素是否在可视区域内 */
  是否在可视区域(完全在视口内 = false) {
    const 位置 = this.getBoundingClientRect();
    const 视口宽度 = window.innerWidth || document.documentElement.clientWidth;
    const 视口高度 = window.innerHeight || document.documentElement.clientHeight;
    
    if (完全在视口内) {
      return 位置.top >= 0 && 
             位置.left >= 0 && 
             位置.bottom <= 视口高度 && 
             位置.right <= 视口宽度;
    } else {
      return 位置.bottom > 0 && 
             位置.top < 视口高度 && 
             位置.right > 0 && 
             位置.left < 视口宽度;
    }
  }

  /** 滚动到元素 */
  滚动到(选项 = {}) {
    this._元素.scrollIntoView(选项);
    return this;
  }

  /** 焦点操作 */
  聚焦(选项 = {}) {
    this._元素.focus(选项);
    return this;
  }

  /** 失焦 */
  失焦() {
    this._元素.blur();
    return this;
  }

  /** 是否有焦点 */
  有焦点() {
    return document.activeElement === this._元素;
  }

  /** 设置数据属性 */
  设置数据(键, 值) {
    this._元素.dataset[键] = 值;
    return this;
  }

  /** 获取数据属性 */
  获取数据(键) {
    return this._元素.dataset[键];
  }

  /** 获取所有数据属性 */
  获取所有数据() {
    return { ...this._元素.dataset };
  }
}

// 添加addTo方法以支持链式调用中的添加操作
DOM操作.prototype.addTo = function(父元素) {
  const 父 = 父元素 instanceof DOM操作 ? 父元素.取值() : 父元素;
  父.appendChild(this.取值());
  return this;
};

// 静态工厂方法
DOM操作.查找 = (选择器) => new DOM操作(选择器);
DOM操作.查找所有 = (选择器) => Array.from(document.querySelectorAll(选择器)).map(元素 => new DOM操作(元素));

// 规范导出
export { DOM操作 };
export default DOM操作;